#include "button.h"

//用来判断按键行为的定时器
Ticker tickerButton1;
Ticker tickerButton2;
Ticker tickerButton3;
Ticker tickerButton4;

//用作4个按键消抖的定时器
Ticker button_clear_chattering;

struct Button
{
    const uint8_t PIN;//引脚
    bool pressed;//按键按下标记
    uint8_t key_flag;//按键当前动作
    uint8_t cur_tick;//按键计数
    Ticker *tick;
    void (*callback)(void);
};

//按键行为定时器回调函数声明
void Button1_tick(void);
void Button2_tick(void);
void Button3_tick(void);
void Button4_tick(void);

//按键消抖定时器回调函数声明
void ticker_for_clear_up_chattering(void);

Button button1 = {26,false,0,0,&tickerButton1,Button1_tick};
Button button2 = {21,false,0,0,&tickerButton2,Button2_tick};
Button button3 = {12,false,0,0,&tickerButton3,Button3_tick};
Button button4 = {13,false,0,0,&tickerButton4,Button4_tick};

void Button1_tick(void)
{
    //判断是否按键已按下一次
    if(button1.pressed == true)
    {
        //如果500ms仍检测到按键按下
        if(digitalRead(button1.PIN) == LOW)
        {
            button1.cur_tick++;
            if(button1.cur_tick >= 3)
            {
                button1.key_flag = 2;//长按
                button1.tick->detach();//关闭定时器
                button1.pressed = false;
            }
        }
        else//如果500ms后按键没按下
        {
            button1.key_flag = 1;//短按
            button1.tick->detach();//关闭定时器
            button1.pressed = false;
        }
    }
}

void Button2_tick(void)
{
    if(button2.pressed == true)
    {
        if(digitalRead(button2.PIN) == LOW)
        {
            button2.cur_tick++;
            if(button2.cur_tick >= 3)
            {
                button2.key_flag = 2;
                button2.tick->detach();
                button2.pressed = false;
            }
        }
        else
        {
            button2.key_flag = 1;
            button2.tick->detach();
            button2.pressed = false;
        }
    }
}

void Button3_tick(void)
{
    if(button3.pressed == true)
    {
        if(digitalRead(button3.PIN) == LOW)
        {
            button3.cur_tick++;
            if(button3.cur_tick >= 3)
            {
                button3.key_flag = 2;
                button3.tick->detach();
                button3.pressed = false;
            }
        }
        else
        {
            button3.key_flag = 1;
            button3.tick->detach();
            button3.pressed = false;
        }
    }
}

void Button4_tick(void)
{
    if(button4.pressed == true)
    {
        if(digitalRead(button4.PIN) == LOW)
        {
            button4.cur_tick++;
            if(button4.cur_tick >= 3)
            {
                button4.key_flag = 2;
                button4.tick->detach();
                button1.pressed = false;
            }
        }
        else
        {
            button4.key_flag = 1;
            button4.tick->detach();
            button4.pressed = false;
        }
    }
}

void ticker_for_clear_up_chattering(int arg)
{
    //Button *s = static_cast<Button *>(arg);

    if(digitalRead(arg) == LOW)
    {
        button_clear_chattering.detach();//关闭消抖定时器
        if(arg == button1.PIN)//如果消抖后探测到是按键1按下
        {
            //Serial.println("button1 press");
            if(button1.pressed == true)
            {
                button1.key_flag = 3;
                button1.tick->detach();
                button1.pressed = false;
            }
            else
            {
                button1.pressed = true;
                button1.tick->attach_ms(500,button1.callback);
            } 
        }
        else if(arg == button2.PIN)
        {
            if(button2.pressed == true)
            {
                button2.key_flag = 3;
                button2.tick->detach();
                button2.pressed = false;
            }
            else
            {
                button2.pressed = true;
                button2.tick->attach_ms(500,button2.callback);
            }
        }
        else if(arg == button3.PIN)
        {
            if(button3.pressed == true)
            {
                button3.key_flag = 3;
                button3.tick->detach();
                button3.pressed = false;
            }
            else
            {
                button3.pressed = true;
                button3.tick->attach_ms(500,button3.callback);
            }
        }
        else if(arg == button4.PIN)
        {
            //Serial.println("button4 press");
            if(button4.pressed == true)
            {
                button4.key_flag = 3;
                button4.tick->detach();
                button4.pressed = false;
            }
            else
            {
                button4.pressed = true;
                button4.tick->attach_ms(500,button4.callback);
            }
        }
    }
}

void IRAM_ATTR isr(void *arg)
{
    //将指针arg的类型进行强制转换成Button *
    Button *s = static_cast<Button *>(arg);

    if(digitalRead(s->PIN) == LOW)
    {
        button_clear_chattering.attach_ms(10,ticker_for_clear_up_chattering,(int)s->PIN);
    }

    // //如果某个按键检测到按下
    // if(digitalRead(s->PIN) == LOW)
    // {
    //     // if(s->pressed == true)//如果该按键之前有被按下,也就是500ms之内连按了两次
    //     // {
    //     //     s->key_flag = 3;//连按
    //     //     s->tick->detach();
    //     //     s->pressed = false;
    //     // }
    //     // else//如果该按键之前没被按下过,则证明是第一次按该按键 
    //     // {
    //     //     s->pressed = true;//设置按键标志
    //     //     //s->tick->attach_ms(500,s->callback);//打开定时器
            
    //     //     button_clear_chattering.attach_ms(10,ticker_for_clear_up_chattering,(int)s->PIN);
    //     // }
    //     button_clear_chattering.attach_ms(10,ticker_for_clear_up_chattering,(int)s->PIN);
        
    // }
    // else
    // {

    // }

}

//按键初始化
void button_Init(void)
{
    pinMode(button1.PIN,INPUT_PULLUP);
    attachInterruptArg(button1.PIN,isr,&button1,FALLING);

    pinMode(button2.PIN,INPUT_PULLUP);
    attachInterruptArg(button2.PIN,isr,&button2,FALLING);

    pinMode(button3.PIN,INPUT_PULLUP);
    attachInterruptArg(button3.PIN,isr,&button3,FALLING);

    pinMode(button4.PIN,INPUT_PULLUP);
    attachInterruptArg(button4.PIN,isr,&button4,FALLING);
}

uint8_t get_button_state(void)
{
    uint8_t flag;

    if (button1.key_flag != 0)
    {
        flag = button1.key_flag;
        button1.key_flag = 0;
        if(flag == 2)
        {
            return BUTTON1_LONG_PUSH;
        }
        else if(flag == 3)
        {
            return BUTTON1_TWO_PUSH;
        }

        return BUTTON1_PUSH;
    }

    if (button2.key_flag != 0)
    {
        flag = button2.key_flag;
        button2.key_flag = 0;
        if(flag == 2)
        {
            return BUTTON2_LONG_PUSH;
        }
        else if(flag == 3)
        {
            return BUTTON2_TWO_PUSH;
        }

        return BUTTON2_PUSH;
    }

    if (button3.key_flag != 0)
    {
        flag = button3.key_flag;
        button3.key_flag = 0;
        if(flag == 2)
        {
            return BUTTON3_LONG_PUSH;
        }
        else if(flag == 3)
        {
            return BUTTON3_TWO_PUSH;
        }

        return BUTTON3_PUSH;
    }

    if (button4.key_flag != 0)
    {
        flag = button4.key_flag;
        button4.key_flag = 0;
        if(flag == 2)
        {
            return BUTTON4_LONG_PUSH;
        }
        else if(flag == 3)
        {
            return BUTTON4_TWO_PUSH;
        }
        return BUTTON4_PUSH;
    }  
    return 0;
}